/**
 * The main UI class
 * @class syslib.ui
 * @version 0.5.3
 * @author Gabriel Ricci - gabrielricci@gmail.com
 * @static
 */
syslib.ui = {
	/** 
	 * The version
	 */ 
	version : "0.5.3",
	
	/**
	 * The status, to avoid more than one UI initialization
	 */
	started : false, 
	
	init: function(){
		if(this.started){
			return true;
		}
	
		// try to register the tags
		this.registerTags();

		// get the options
		var options = syslib.options;

		// load the effects
		if(__valid(options.enableFX)){
			// search the effects
			for(var i = 0; i < options.effects.length; i++){
				// get the effect
				var effect = options.effects[i];
				
				// load
				syslib.ui.fx.load(effect);
			}
		}
		
		// set as started
		this.started = true;
		
		// parse the body
		syslib.taglib.parseBody();
	},
	
	/**
	 * Register the components on the core of the lib
	 */
	registerTags : function(){
		// LOG
		syslib.messages.info("syslib.ui.registerTags(): Registering core tags");
		
		// REGISTER THE CORE TAGS
		syslib.taglib.registerTag('box', {
			packageName : "syslib.ui.Box",
			parser : "syslib.ui.Box"
		});
		syslib.taglib.registerTag('dialog', {
			packageName : "syslib.ui.Dialog",
			parser : "syslib.ui.DialogTag"
		});
		syslib.taglib.registerTag('tabpanel', {
			packageName : "syslib.ui.TabPanel",
			parser : "syslib.ui.TabPanel"
		});
		syslib.taglib.registerTag('tabitem', {
			packageName : "syslib.ui.TabItem",
			parser : "syslib.ui.TabItem"
		});
		syslib.taglib.registerTag('accordeonmenu', {
			packageName : "syslib.ui.Accordeon",
			parser : "syslib.ui.Accordeon.Conversor"
		});
		syslib.taglib.registerTag('accordeonitem', {
			packageName : "syslib.ui.AccordeonItem",
			parser : "syslib.ui.AccordeonItem.Conversor"
		});
		syslib.taglib.registerTag('wizardpanel', {
			packageName : "syslib.ui.WizardPanel",
			parser : "syslib.ui.WizardPanel.Conversor"
		});
		syslib.taglib.registerTag('wizardstep', {
			packageName : "syslib.ui.WizardStep",
			parser : "syslib.ui.WizardStep.Conversor"
		});
		syslib.taglib.registerTag('texteditor', {
			packageName : "syslib.ui.TextEditor",
			parser : "syslib.ui.TextEditor"
		});
		syslib.taglib.registerTag('xsplitterpanel', {
			packageName : "syslib.ui.XSplitterPanel",
			parser : "syslib.ui.XSplitterPanel"
		});
		syslib.taglib.registerTag('xsplitteritem', {
			packageName : "syslib.ui.XSplitterItem",
			parser : "syslib.ui.XSplitterItem"
		});
		syslib.taglib.registerTag('spinner', {
			packageName : "syslib.ui.Spinner",
			parser :  "syslib.ui.Spinner",
			innerContent : false
		});
		syslib.taglib.registerTag('calendar', {
			packageName : "syslib.ui.Calendar",
			parser :  "syslib.ui.Calendar",
			innerContent : false
		});
		syslib.taglib.registerTag('maskinput', {
			packageName : "syslib.ui.MaskInput",
			parser : "syslib.ui.MaskInput",
			innerContent : false
		});
		syslib.taglib.registerTag('tooltip', {
			packageName : "syslib.ui.Tooltip",
			parser : "syslib.ui.Tooltip"
		});
		syslib.taglib.registerTag('buttonmenu', {
			packageName : "syslib.ui.ButtonMenu",
			parser : "syslib.ui.ButtonMenu"
		});
		syslib.taglib.registerTag('buttonitem', {
			packageName : "syslib.ui.ButtonItem",
			parser : "syslib.ui.ButtonItem"
		});
		syslib.taglib.registerTag('panel', {
			packageName : "syslib.ui.Panel",
			parser : "syslib.ui.Panel"
		});
		syslib.taglib.registerTag('horizontalseparator', {
			packageName : "syslib.ui.HorizontalSeparator",
			parser : "syslib.ui.HorizontalSeparator", 
			innerContent : false
		});
		syslib.taglib.registerTag('verticalseparator', {
			packageName : "syslib.ui.VerticalSeparator",
			parser : "syslib.ui.VerticalSeparator", 
			innerContent : false
		});
		syslib.taglib.registerTag('toolbar', {
			packageName : "syslib.ui.Toolbar",
			parser : "syslib.ui.Toolbar"
		});
		syslib.taglib.registerTag('simplebutton', {
			packageName : "syslib.ui.SimpleButton",
			parser : "syslib.ui.SimpleButton"
		});
		syslib.taglib.registerTag('progressbar', {
			packageName : "syslib.ui.ProgressBar",
			parser :  "syslib.ui.ProgressBar",
			innerContent : false
		});
	}
};

/**
 * The element positioning class
 * @class syslib.ui.position
 * @author Gabriel Ricci
 * @static
 */
syslib.ui.position = {
	center : function(element, options){
		options = syslib.object.extend({}, options);

		element.style.position = 'absolute';
		element.parentNode.removeChild(element);
		document.body.appendChild(element);

		var Dimensions = syslib.element.getDimensions(element);

		var leftMiddle = document.body.scrollLeft + ( document.body.clientWidth / 2);
		var topMiddle = document.body.scrollTop + ( document.body.clientHeight / 2);

		var posx = leftMiddle - (Dimensions.width / 2);
		var posy = topMiddle - (Dimensions.height / 2);

		element.style.left = posx + "px";
		element.style.top = posy + "px";

		if(options.setEvent !== false){
			syslib.event.listen('resize', window, function(){
				syslib.ui.position.center(element, syslib.object.extend(options, {
					setEvent : false
				}));
			});
		}
	},

	getOffsets : function(element){
		element = __id(element);
		var top = 0; var left = 0;
		while (element.offsetParent){
			left 	+= element.offsetLeft;
			top  	+= element.offsetTop;
			element	=  element.offsetParent;
		}

		left += element.offsetLeft;
		top  += element.offsetTop;

		return {x: left, y: top};
	}, 
	
	getAbsolutePosition : function(element){
		var top		= 0;
		var left		= 0;

		try{
			while(syslib.util.valid(element.offsetParent)){
				left += (element.offsetLeft - element.offsetParent.scrollLeft);
				top  += (element.offsetTop - element.offsetParent.scrollTop);
				element = element.offsetParent;
			}
			top  += (element.offsetLeft);
			left += (element.offsetTop);
		} catch(e){
			alert(e.message);
		}

		return {x: left, y: top};
	}
};

/**
 * The element size controling class
 * @class syslib.ui.size
 * @author Gabriel Ricci
 * @static
 */
syslib.ui.size = {
	setFullHeight : function(element, options){
		// get the element
		var element = __id(element);
		
		// check if the element is valid
		if(!__valid(element)){ return false; }
		
		// get the element absolute position and the window size
		var absPosition 	= syslib.ui.position.getAbsolutePosition(element);
		var windowSize	= this.getWindowSize(element);
		
		// format the options
		options = syslib.object.extend({
			setEvent : true, 
			overflow : "auto"
		}, options);
		
		// calcule the height
		var height = windowSize.height - absPosition.y;
		
		// check if padding is needed
		if(__valid(options.padding) && !isNaN(options.padding)){
			height -= options.padding;
		}

		// update the height
		syslib.element.updateStyle(element, {
			"height" : height + "px", 
			"overflow" : options.overflow 
		});

		// set the event
		if(options.setEvent !== false || options.setEvent === undefined){
			syslib.event.listen('resize', window, function(){
				syslib.ui.size.setFullHeight(element, syslib.object.extend(options, {
					setEvent : false 
				}));
			});
		}
	},
	getOffsets : function(element){
		element = __id(element);
		return {width: element.offsetWidth, height: element.offsetHeight};
	}, 
	getWindowSize : function(){
		return this.getOffsets(document.body);
	}
};

/**
 * The user-interface utilities class
 * @class syslib.ui.util
 * @author Gabriel Ricci
 * @static
 */
syslib.ui.util = {
	toggleChecks : function(controller, container){
		container = __id(container);
		if(!__valid(container)){alert('invalid!'); return false;}

		var checks = container.getElementsByTagName("input");
		for(var i = 0; i < checks.length; i++){
			var check = checks[i];
			if(check.getAttribute("type") != "checkbox" || check == controller || check.disabled === true){ continue; }
			check.checked = controller.checked;
		}
	}
};

/**
 * The basic tag class, this is the basic superclass of any tag conversor
 * @class syslib.ui.BasicTag
 * @author Gabriel Ricci
 * @static
 */
syslib.ui.BasicTag = {
	__type : syslib.taglib.TYPE_BASIC, 
	__tagName : null,
	__parentTagName : null,
	__parent : null,
	__attributes : null, 
	__innerHTML	: null, 

	__construct : function(){
		__tagName = null;
		__parentTagName = null;
		__parent = null;
		__attributes = null;
		__innerHTML = null; 
	}
};

/**
 * The visual tag class, this is the required superclass of any visual tag conversor
 * @class syslib.ui.VisualTag
 * @author Gabriel Ricci
 * @static
 */
syslib.ui.VisualTag = {
	__type : syslib.taglib.TYPE_VISUAL,
	__tagName : null,
	__parentTagName : null,
	__parent : null,
	__attributes : null, 
	__innerHTML	: null, 
	__jsonStruct : null,
	__element : null, 
	__refs : null,   
	__appendTo : null, 
	
	__construct : function(){
		__tagName = null;
		__parentTagName = null;
		__parent = null;
		__innerHTML = null;  
		__attributes = null;
		__jsonStruct = null;
		__element = null;
		__refs = null;
	}, 
	
	createDOM : function(json){
		this.__jsonStruct = json;
		var created = syslib.element.createFromJSON(false, json);
		this.__element = created.element;
		this.__refs = created.references;
		
		return this.__element;
	}
};


/**
 * Drag class
 * Options:
 *   - onstartdrag : function(element, controller) - Function called when the drag starts;
 *   - onstopdrag : function(element, controller) - Function called when the drag ends;
 *   - ondragging : function(element, controller) - Function called when dragging;
 *   - xmove : boolean(true, false) - Enable or disable the X moving;
 *   - ymove : boolean(true, false) - Enable or disable the Y moving;
 *   - alpha : boolean(true, false) - Enable or disable alpha when dragging;
 *   - reset : boolean(true, false) - Aways reset the element to the start position
 * @class syslib.ui.Drag
 * @author Gabriel Ricci
 */
syslib.ui.Drag = __class();
syslib.ui.Drag.prototype = {
	dragActive : false,
	mouseOffset : null,
	_origAttributes : {},
	enabled : true,
	drops : null,
	parent : null,
	brother : null,

	controller: null,
	element: null,
	options: {},

	__construct : function(controller, element, opts){
		if(__id(controller) && __id(element)){
			this.controller = __id(controller);
			this.element 	= __id(element);
		} else { return false; }

		if(typeof opts == 'object'){
			this.options = opts;
		} else {
			this.options = {};
		}

		this.drops 	 = [];
		this.parent  = this.element.parentNode;

		if(syslib.dom.next(this.element) !== undefined){
			this.brother = syslib.dom.next(this.element);
		} else if(syslib.dom.previous(this.element) !== undefined){
			this.brother = syslib.dom.previous(this.element);
		} else {
			this.brother = false;
		}

		syslib.element.updateStyle(this.controller, {
			cursor: 'move'
		});

		syslib.event.listen('mousedown', this.controller, this.mouseDown.applyTo(this));
		syslib.event.listen('mousemove', document, this.mouseMove.applyTo(this));
		syslib.event.listen('mouseup', document, this.mouseUp.applyTo(this));
	},

	disable : function(){
		this.enabled = false;
		syslib.messages.info("Drag " + this.controller.id + " was been disabled");
	},

	enable : function(){
		this.enabled = true;
		syslib.messages.info("Drag " + this.controller.id + " was been enabled");
	} ,

	mouseDown : function(evt){
		if(this.enabled === false || syslib.event.isLeftClick(evt) === false){
			return false;
		}

		this.dragActive  			  	= true;
		this._origAttributes.zIndex	  	= this.element.style.zIndex;
		this._origAttributes.position 	= this.element.style.position;
		this._origAttributes.left		= this.element.style.left;
		this._origAttributes.top		= this.element.style.top;
		this._origAttributes.margin		= this.element.style.margin;
		this.mouseOffset 			  	= this.getMouseOffset(evt);

		var realpos						= this.getRealPosition(this.element);

		syslib.element.updateStyle(this.element, {
			position: 'absolute',
			margin: '0',
			zIndex: parseInt(syslib.ui.Drag.zIndex++),
			left: realpos[0],
			top: realpos[1]
		});

		if(this.options.alpha === true){
			syslib.element.updateStyle(this.element, {
				'filter': 'alpha(opacity=50)',
				'-moz-opacity': '.50',
				'opacity': '.50'
			});
		}

		this.element.parentNode.removeChild(this.element);
		document.body.appendChild(this.element);

		if(typeof this.options.onStart === 'function'){this.options.onStart(this.element, this.controller);}
		syslib.messages.info("Drag " + this.controller.id + " started");
		
		return false;
	},

	mouseUp : function(evt){
		if(this.dragActive === true){
			this.dragActive = false;

			if(this.options.alpha === true){
				syslib.element.updateStyle(this.element, {
					'filter': 'alpha(opacity=100)',
					'-moz-opacity': '1',
					'opacity': '1'
				});
			}

			for(var i = 0; i < this.drops.length; i++){
				var drop   = this.drops[i];
				var psdrop = drop.getCoords();
				var mousex = syslib.event.mouseX(evt);
				var mousey = syslib.event.mouseY(evt);

				if(mousex >= psdrop.x1 && mousex <= psdrop.x2 && mousey >= psdrop.y1 && mousey <= psdrop.y2){
					drop.onDrop(this.element);
				}
			}

			if(this.options.reset){
				syslib.element.updateStyle(this.element, {
					position: this._origAttributes.position,
					top: this._origAttributes.top,
					left: this._origAttributes.left,
					margin: this._origAttributes.margin,
					zIndex: this._origAttributes.zIndex
				});
				if(this.brother){
					this.parent.insertBefore(this.element, this.brother);
				} else {
					this.parent.appendChild(this.element);
				}
			}

			this.deactivateDrops();
			if(typeof this.options.onEnd === 'function'){this.options.onEnd(this.element, this.controller);}
			syslib.messages.info("Drag " + this.controller.id + " ended");
		}
	},

	mouseMove : function(evt){
		if(this.dragActive === true){
			var mousePos 	= [syslib.event.mouseX(evt), syslib.event.mouseY(evt)];
			var left		= (parseInt(mousePos[0]) - parseInt(this.mouseOffset[0])) + 'px';
			var top			= (parseInt(mousePos[1]) - parseInt(this.mouseOffset[1])) + 'px';

			if(this.options.xmove !== false){
				this.element.style.left = left;
			}

			if(this.options.ymove !== false){
				this.element.style.top = top;
			}

			if(typeof this.options.onDrag == 'function'){this.options.onDrag(this.element, this.controller);}

			for(var i = 0; i < this.drops.length; i++){
				var drop   = this.drops[i];
				var psdrop = drop.getCoords();
				var mousex = syslib.event.mouseX(evt);
				var mousey = syslib.event.mouseY(evt);

				if(mousex >= psdrop.x1 && mousex <= psdrop.x2 && mousey >= psdrop.y1 && mousey <= psdrop.y2){
					if(!drop.active){ drop.activate(this.element); }
				} else {
					if(drop.active){ drop.deactivate(this.element); }
				}
			}
		}
	},

	registerDroppable : function(droppable){
		if(droppable.type === 'droppable'){
			this.drops.push(droppable);
			syslib.messages.info("Droppable " + droppable.element.id + " registered on drag " + this.controller.id);
		} else {
			syslib.messages.error("Drop " + droppable.element.id + " is invalid an could not be registered!");
		}

	},

	deactivateDrops : function(){
		for(var i = 0; i < this.drops.length; i++){
			var drop = this.drops[i];
			drop.deactivate(this.element);
		}
	},

	getRealPosition : function(element){
		var top			= 0;
		var left		= 0;

		try{
			while(syslib.util.valid(element.offsetParent)){
				left += (element.offsetLeft - element.offsetParent.scrollLeft);
				top  += (element.offsetTop - element.offsetParent.scrollTop);
				element = element.offsetParent;
			}
			top  += (element.offsetLeft);
			left += (element.offsetTop);
		} catch(e){
			alert(e.message);
		}

		return [left, top];
	},

	getMouseOffset : function(evt){
		try{
			var mousepos 	= [syslib.event.mouseX(evt), syslib.event.mouseY(evt)];
			var elemtpos	= this.getRealPosition(this.element);

			return [mousepos[0] - elemtpos[0], mousepos[1] - elemtpos[1]];
		} catch(e){
			alert(e.message);
		}
	}
};
syslib.ui.Drag.zIndex = 1500;

/**
 * Drop class
 * @class syslib.ui.Drop
 * @author Gabriel Ricci
 */
syslib.ui.Drop = __class();
syslib.ui.Drop.prototype = {
	type : 'droppable',
	element : null,
	options : {},

	active : false,

	__construct : function(element, options){
		if(__id(element)){
			this.element = __id(element);
		} else {
			return false;
		}

		if(typeof options == 'object'){
			this.options = options;
		}
	},

	onDrop : function(dropped){
		if(typeof this.options.onDrop === 'function'){
			this.options.onDrop(this.element, dropped);
		}
	},

	activate : function(drag){
		this.active = true;
		if(typeof this.options.onEnable === 'function'){
			this.options.onEnable(this.element, drag);
		}
	},

	deactivate : function(drag){
		this.active = false;
		if(typeof this.options.onDisable === 'function'){
			this.options.onDisable(this.element, drag);
		}
	},

	getOffset : function(){
		var top = 0; var left = 0; element = this.element;
		while (element.offsetParent){
			left 	+= element.offsetLeft;
			top  	+= element.offsetTop;
			element	=  element.offsetParent;
		}

		left += element.offsetLeft;
		top  += element.offsetTop;

		return {x: left, y: top};
	},

	getCoords : function(){
		var offset 	= this.getOffset();
		var dimens	= Element.getDimensions(this.element);

		return {x1: offset.x, x2: offset.x + dimens.width, y1: offset.y, y2: offset.y + dimens.height};
	}
};

/**
 * The effects class
 * @class syslib.ui.fx
 * @author Gabriel Ricci
 * @static
 */
syslib.ui.fx = {
	MOVE 	: "syslib.ui.fx.Move",
	RESIZE 	: "syslib.ui.fx.Resize",
	ALPHA 	: "syslib.ui.fx.Alpha",
	
	isLoaded : function(effect){
		return __valid(effect);
	},   
	
	load : function(effect){
		// log
		syslib.messages.info("syslib.ui.fx.load(): Loading effect " + effect);
		
		// load
		syslib.io.importClass(effect, {
			onComplete : function(){
				syslib.messages.info("syslib.ui.fx.load(): Effect " + effect + " loaded");
			}
		});
	}
};